package com.itheima.weirpc.server;



import com.itheima.weirpc.RpcApplication;
import com.itheima.weirpc.model.RpcRequest;
import com.itheima.weirpc.model.RpcResponse;
import com.itheima.weirpc.registry.LocalRegistry;
import com.itheima.weirpc.serializer.JdkSerializer;
import com.itheima.weirpc.serializer.Serializer;
import com.itheima.weirpc.serializer.SerializerFactory;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;

import java.io.IOException;
import java.lang.reflect.Method;

/**
 * HTTP 请求处理
 * 对请求进行处理。跟netty中的handler类似
 */
/*
如果开发者想要替换为别的序列化器，就必须修改所有的上述代码，太麻烦了！
理想情况下，应该可以通过配置文件来指定使用的序列化器。在使用序列化器时，根据居配置来获取不同的序列化器实例即可。
这个操作并不难，我们只需要定义一个序列化器名称=>序列化器实现类对象的Map,然后根据名称从Map中获取对象即可

如果开发者不想使用我们框架内置的序列化器，想要自己定义一个新的序列化器实现，但不能修改我们写好的框架代码，应该怎么办呢？
思路很简单：只要我们的RPC框架能狗够读取到用户自定义的类路径，然后加载这个类，作为Serializer序列化器接口的实现即可。
但是如何实现这个操作呢？
这就需要我们学习一个新的概念，也是Java中的重要特性一SPI机制。
 */

public class HttpServerHandler implements Handler<HttpServerRequest> {

    // 指定序列化器
    final Serializer serializer = SerializerFactory.getInstance(RpcApplication.getRpcConfig().getSerializer());


    @Override
    public void handle(HttpServerRequest request) {
//        // 指定序列化器
//        final Serializer serializer = new JdkSerializer();

        // 记录日志
        System.out.println("Received request: " + request.method() + " " + request.uri());
        // 异步处理 HTTP 请求
        request.bodyHandler(body -> {
            byte[] bytes = body.getBytes();
            RpcRequest rpcRequest = null;
            try {
                //反序列化
                rpcRequest = serializer.deserialize(bytes, RpcRequest.class);
            } catch (Exception e) {
                e.printStackTrace();
            }

            // 构造响应结果对象
            RpcResponse rpcResponse = new RpcResponse();
            // 如果请求为 null，直接返回
            if (rpcRequest == null) {
                rpcResponse.setMessage("rpcRequest is null");
                doResponse(request, rpcResponse, serializer);
                return;
            }

            try {
                // 获取要调用的服务实现类，通过反射调用
                Class<?> implClass = LocalRegistry.get(rpcRequest.getServiceName());
                Method method = implClass.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
                Object result = method.invoke(implClass.newInstance(), rpcRequest.getArgs());
                // 封装返回结果
                rpcResponse.setData(result);
                rpcResponse.setDataType(method.getReturnType());
                rpcResponse.setMessage("ok");
            } catch (Exception e) {
                e.printStackTrace();
                rpcResponse.setMessage(e.getMessage());
                rpcResponse.setException(e);
            }
            // 响应 下面的函数
            doResponse(request, rpcResponse, serializer);
        });
    }

    /**
     * 响应
     *
     * @param request
     * @param rpcResponse
     * @param serializer
     */
    void doResponse(HttpServerRequest request, RpcResponse rpcResponse, Serializer serializer) {
        HttpServerResponse httpServerResponse = request.response()
                .putHeader("content-type", "application/json");
        try {
            // 序列化
            byte[] serialized = serializer.serialize(rpcResponse);
            httpServerResponse.end(Buffer.buffer(serialized));
        } catch (IOException e) {
            e.printStackTrace();
            httpServerResponse.end(Buffer.buffer());
        }
    }
}
